import turbogears
from basesa import model
import pkg_resources
pkg_resources.require("SQLAlchemy>=0.4")

from sqlalchemy import Table, Column, Integer, String, DateTime, ForeignKey
from sqlalchemy.orm import relation
from turbogears.database import metadata, session, mapper
from datetime import datetime
from turbogears import config
from registration.ormmanager import count

def create_registration_tables():
    "Create the appropriate database tables."
    registration_pending_user_table.create(checkfirst=True)
    email_change_table.create(checkfirst=True)

# Automatically create the registration tables when TurboGears starts up
# turbogears.startup.call_on_startup.append(create_registration_tables)


_user_path = config.get('identity.saprovider.model.user',
                                        'basesa.model.User')
User = turbogears.util.load_class(_user_path)
                                        


registration_pending_user_table = Table('registration_pending_user', metadata,
                                        Column('id', Integer, primary_key=True),
                                        Column('user_name', String(16), nullable=False, unique=True),
                                        Column('email_address', String(255), nullable=False, unique=True),
                                        Column('display_name', String(255)),
                                        Column('password', String(40)),
                                        Column('created', DateTime, default=datetime.now),
                                        Column('validation_key', String(40))
                                        )

class RegistrationPendingUser(object):
    
    def __repr__(self):
        return "RegistrationPendingUser id:%d user_name:%s email_address: %s" % \
                    (self.id, self.user_name, self.email_address)

mapper(RegistrationPendingUser, registration_pending_user_table)

email_change_table = Table('registration_user_email_change', metadata,
                            Column('id', Integer, primary_key=True),
                            # TODO: should probably make finding the user_id column
                            # more generic
                            Column('user_id', Integer, ForeignKey('tg_user.user_id')),
                            Column('new_email_address', String(255), nullable=False, unique=True),
                            Column('validation_key', String(40), nullable=False),
                            Column('created', DateTime, default=datetime.now)
                        )
    
class RegistrationUserEmailChange(object):
    
    def __repr__(self):
        return "RegistrationUserEmailChange id:%d user_id:%d new_email_address:%s " + \
                "validation_key: %s" % (self.id, self.user_id, self.new_email_address, 
                                        self.validation_key)
            
    @classmethod
    def get_by_new_email(cls, new_email_address):
        "Returns an existing object using new_email_address as the lookup item."
        return session.query(cls).get_by(new_email_address=new_email_address)
    
        
mapper(RegistrationUserEmailChange, email_change_table,
            properties=dict(user=relation(User)))


def user_name_is_unique(user_name):
    "Return True if the user_name is not yet in the database."
    user_count = count(User, user_name=user_name)
    pending_count = count(RegistrationPendingUser, user_name=user_name)
    return not(user_count or pending_count)

        
def email_is_unique(email):
    "Return True if the email is not yet in the database."
    user_count = count(User, email_address=email)
    pending_count = count(RegistrationPendingUser, email_address=email)
    changed_count = count(RegistrationUserEmailChange, new_email_address=email)
    return not(user_count or pending_count or changed_count)
